/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package documentadorrepositorio.repositorio;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.tmatesoft.svn.core.SVNDirEntry;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNProperty;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.internal.util.SVNDate;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

/**
 *
 * @author André
 */
public class GerenciadorRepositorioSVN implements IGerenciadorRepositorio
{

    SVNRepository repositorio = null;
    String pastaRoot = "";
    String caminhoRepositorio = "";
    String usuarioRepositorio = "";
    String senhaRepositorio = "";

    public GerenciadorRepositorioSVN()
    {
    }

    @Override
    public void iniciaGerenciador(String caminhoRepositorio, String usuario, String senha) throws Exception
    {
        configuraBiblioteca();

        this.caminhoRepositorio = caminhoRepositorio;
        this.usuarioRepositorio = usuario;
        this.senhaRepositorio = senha;

        repositorio = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(caminhoRepositorio));

        ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(this.usuarioRepositorio, this.senhaRepositorio);
        repositorio.setAuthenticationManager(authManager);

        verificaCaminhoRepositorio();

        this.pastaRoot = repositorio.getRepositoryRoot(true).toString();
    }

    public String obtemPastaRoot()
    {
        return pastaRoot;
    }

    public ArquivoVersionado obtemDadosArquivo(String caminho) throws Exception
    {
        SVNProperties properties = new SVNProperties();
        ByteArrayOutputStream bytesArquivo = new ByteArrayOutputStream();
        repositorio.getFile(caminho, -1, properties, bytesArquivo);
        ArquivoVersionado dadosArquivo = new ArquivoVersionado();
        dadosArquivo.setCaminhoArquivo(caminho);
        dadosArquivo.setBytesArquivo(bytesArquivo);
        dadosArquivo.setDataCommit(SVNDate.parseDate(properties.getStringValue(SVNProperty.COMMITTED_DATE)));
        dadosArquivo.setRevisao(Integer.parseInt(properties.getStringValue(SVNProperty.REVISION)));
        //dadosArquivo.setPropriedadesArquivo(properties);
        return dadosArquivo;
    }

    // onde é usada?
    //------------------------------------------------------------------------------------
    public List<String> obtemEntradas(String caminho) throws Exception
    {
        Collection entradas = repositorio.getDir(caminho, -1, null, (Collection) null);
        List<String> caminhos = new ArrayList<>();
        Iterator iterador = entradas.iterator();
        while (iterador.hasNext())
        {
            SVNDirEntry entrada = (SVNDirEntry) iterador.next();
            String textoEntrada = "";
            if (entrada.getKind() == SVNNodeKind.DIR)
            {
                textoEntrada = "+ ";
            } else
            {
                textoEntrada = "  ";
            }
            textoEntrada += entrada.getName();
            caminhos.add(textoEntrada);
        }
        return caminhos;
    }

    public Iterator obtemIteradorPasta(String caminho) throws Exception
    {
        Collection entradas = repositorio.getDir(caminho, -1, null, (Collection) null);;
        return entradas.iterator();
    }

    public List<String> obtemArquivos(String caminho) throws Exception
    {
        List<String> pastas = new ArrayList<>();
        Iterator iterador = obtemIteradorPasta(caminho);
        while (iterador.hasNext())
        {
            SVNDirEntry entrada = (SVNDirEntry) iterador.next();
            if (entrada.getKind() == SVNNodeKind.FILE)
            {
                pastas.add(entrada.getName());
            }
        }
        return pastas;
    }

    public List<String> obtemPastas(String caminho) throws Exception
    {
        List<String> pastas = new ArrayList<>();
        Iterator iterador = obtemIteradorPasta(caminho);
        while (iterador.hasNext())
        {
            SVNDirEntry entrada = (SVNDirEntry) iterador.next();
            if (entrada.getKind() == SVNNodeKind.DIR)
            {
                pastas.add(entrada.getName());
            }
        }
        return pastas;
    }

    public void configuraBiblioteca()
    {
        //Habilita protocolo http ou https
        DAVRepositoryFactory.setup();

        //Habilita protocolo svn
        SVNRepositoryFactoryImpl.setup();

        //Habilita para repositório Local
        FSRepositoryFactory.setup();
    }

    public void verificaCaminhoRepositorio() throws Exception
    {
        ///Verifica se o caminho especificado é realmente um diretório. -1 se refere a ultima versão
        SVNNodeKind tipoNo = repositorio.checkPath("", -1);
        if (tipoNo == SVNNodeKind.NONE)
        {
            throw new Exception("Não existe entrada em '" + caminhoRepositorio + "'.");
        } else if (tipoNo == SVNNodeKind.FILE)
        {
            throw new Exception("O Caminho especificado '" + caminhoRepositorio
                    + "' é um arquivo.\nEra esperado um diretório.");
        }
    }
}
